package com.hospital.search.module.utils;

import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import com.hospital.common.dto.search.module.PostQueryDto;
import com.hospital.common.dto.search.module.PostSortDto;
import com.hospital.search.module.base.QueryType;
import com.hospital.search.module.base.SortFlag;
import com.hospital.search.module.base.SortType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.Objects;

@Component
public class PostQueryBuilder {
    @Value("${elastic.index-alias}")
    private String indexAlias;
    public SearchRequest build(PostQueryDto queryDto) {
        SearchRequest.Builder s = new SearchRequest.Builder()
                .index(indexAlias)
                .from((queryDto.getPageNum() - 1) * queryDto.getPageSize())
                .size(queryDto.getPageSize())
                .query(buildQuery(queryDto));
        SortOptions sort = buildSort(queryDto);
        if(!ObjectUtils.isEmpty(sort)){
            s.sort(sort);
        }
        // 排除内容字段
        s.source(src->src.filter(f->f.excludes("content")));
        return s.build();
    }
    private Query buildQuery(PostQueryDto queryDto){
        switch (Objects.requireNonNull(QueryType.getByValue(queryDto.getQueryType()))){
            case NORMAL -> {
                return Query.of(q->q.bool(b->b
                            .should( s->s.match(m->m
                                .field("abstracts").query(queryDto.getQueryContent()))
                            ).should(s->s.match(m->m
                                .field("content").query(queryDto.getQueryContent())))
                            .should(s->s.match(m->m
                                .field("title").query(queryDto.getQueryContent())))));
            }
            case HIGH_LEVEL -> {
                return Query.of(q->q.bool(b->{
                    if(!ObjectUtils.isEmpty(queryDto.getQueryContent())){
                       b.must(m->m.match(mm->mm.field("content").query(queryDto.getQueryContent())));
                       b.should(m->m.match(mm->mm.field("abstracts").query(queryDto.getQueryContent())));
                    }
                    if(!ObjectUtils.isEmpty(queryDto.getSectionName())){
                        b.must(m->m.match(mm->mm.field("sectionName").query(queryDto.getSectionName())));
                    }
                    if(!ObjectUtils.isEmpty(queryDto.getAuthor())){
                        b.must(m->m.match(mm->mm.field("author").query(queryDto.getAuthor())));
                    }
                    if(!ObjectUtils.isEmpty(queryDto.getTitle())){
                        b.must(m->m.match(mm->mm.field("title").query(queryDto.getTitle())));
                    }
                    return b;
                }));
            }
            default -> {
                return Query.of(q->q.matchAll(m->m));
            }
        }
    }
    private SortOptions buildSort(PostQueryDto queryDto){
        PostSortDto sort = queryDto.getSort();
        if(ObjectUtils.isEmpty(sort)){
            return null;
        }
        return SortOptions.of(s->s.field(f->f.field(Objects.requireNonNull(SortType.getByValue(sort.getSortType())).filed)
                .order(Objects.equals(SortFlag.getByValue(sort.getSortFlag()), SortFlag.ASC) ?SortOrder.Asc:SortOrder.Desc)));
    }

}
